<template>
  <vxe-table
    v-bind="{...$attrs,...tableConfig}"
    v-on="{...$listeners,...tableConfig.events}"
    :data="data"
    :edit-config="editConfig"
    :edit-rules="tableEditRules"
    :tooltip-config="tooltipConfigDefault"
    ref="tableRef"
    @checkbox-all="selectAllEvent"
    @checkbox-change="selectChangeEvent"
    @cell-mouseleave="cellMouseleave"
  >
    <template
      v-for="(item,index) in tableConfig.tableItems"
    >
      <TableItem
        v-if="itemShow(item,getSelf)"
        :key="'tableConfig.tableItems'+index"
        :table-item="item"
        :vm="getSelf"
      ></TableItem>
    </template>
  </vxe-table>
</template>

<script>
import {TableConfig} from "./TableType";
import TableItem from './TableItem.vue'
import typeOfUtils from "../../utils/type-of-utils";
import {CommonMixin} from "./Utils/CommonMixin";

import {getNextZIndex} from "@localModules/ZhiXinLib/utils/ElementUIUtils";

export default {
  name: "EditDynamicTable",
  components: {
    TableItem
  },
  mixins:[CommonMixin],
  props: {
    tableConfig: {
      type: TableConfig,
      default: () => {
      }
    },
    data: {
      type: Array,
      default: () => []
    },
    editConfig: {
      type: Object,
      default: () => {
      }
    },
    editRules: {
      type: Object,
      default: () => {
      }
    },
    tooltipConfig: {
      type: Object,
      default: () => {
      }
    }
  },
  watch: {
    'tableConfig.tableItems': {
      handler(val) {
        this.tableEditRules = this.__getEditRules(val)
      },
      deep: true,
      immediate: true
    }
  },
  computed: {
    getSelf() {
      return this
    },
    tooltipConfigDefault(){
      return {
        ...this.tooltipConfig,
        zIndex: this.toolTipZIndex,
      }
    }
  },
  data() {
    return {
      tableEditRules: {},
      toolTipZIndex: getNextZIndex()
    }
  },
  mounted() {
    const validTip = this.$refs.tableRef.$refs.validTip
    if (validTip) {
      const oldOpen = validTip.open
      validTip.open = (target, content) => {
        this.toolTipZIndex = getNextZIndex()
        this.$nextTick(() => {
          oldOpen(target, content)
        })
      }
    }
  },
  methods: {
    // public
    /**
     * 用于 type=checkbox 复选框，设置行为选中状态，第二个参数为选中与否
     * @param rows
     * @param checked
     * @returns {*}
     */
    setCheckboxRow(rows, checked){
      return this.$refs.tableRef.setCheckboxRow(rows, checked)
    },
    /**
     * 列子： const errMap = await this.$refs.EditDynamicTableRef.validate().catch(errMap => errMap)
     *       if (errMap) {
     *         return false;
     *       }
     * @returns {Promise<ColumnEditValidErrMapParams>}
     */
    validate() {
      return new Promise((resolve, reject) => {
        this.$refs.tableRef.fullValidate(true)
          .then(t => resolve(t))
          .catch(e => reject(e))
          .finally(() => {
            this.$nextTick(() => {
              const validTip = this.$refs.tableRef.$refs.validTip
              if (validTip) {
                validTip.updatePlacement()
              }
            })
          })
      })
    },
    /**
     * 给表格添加数据，返回新增的数据
     * @param records {[]|{}} 添加的数据
     * @param row {number} 插入的位置
     * @returns {Promise<[]|{}>}
     */
    async addRow(records, row = -1) {
      const rows = await this.createRow(records)
      if (typeOfUtils.isArray(rows)) {
        if (row === null || row === undefined || row === -1) {
          this.data.push(...rows)
        } else {
          this.data.splice(row, 0, ...rows)
        }
      } else {
        if (row === null || row === undefined || row === -1) {
          this.data.push(rows)
        } else {
          this.data.splice(row, 0, rows)
        }
      }
      return rows
    },
    createRow(records) {
      return this.$refs.tableRef.createRow(records)
    },
    createData(records) {
      return this.$refs.tableRef.createData(records)
    },
    insert(records) {
      return this.$refs.tableRef.insert(records)
    },
    insertAt(records, row) {
      return this.$refs.tableRef.insertAt(records,row)
    },
    getRowIndex(row) {
      return this.$refs.tableRef.getRowIndex(row)
    },
    getColumnIndex(column) {
      return this.$refs.tableRef.getColumnIndex(column)
    },
    refreshColumn() {
      return this.$refs.tableRef.refreshColumn()
    },
    loadData(data) {
      return this.$refs.tableRef.loadData(data)
    },
    /***
     * rows: Row | Row[], record: object, field?: string
     * @param rows
     * @param record
     * @param field
     * @returns {Promise<void>}
     */
    reloadRow(rows, record, field){
      return this.$refs.tableRef.reloadRow(rows, record, field)
    },
    updateStatus(slotParams){
      return this.$refs.tableRef.updateStatus(slotParams)
    },
    // private
    __getEditRules(tableItems = []) {
      let rules = {...this.editRules}
      tableItems.forEach(i => {
        if (i.editRules) {
          rules[i.prop] = i.editRules
        }
        if (i.children && i.children.length > 0) {
          rules = {
            ...rules,
            ...this.__getEditRules(i.children)
          }
        }
      })
      return rules
    },
    //<editor-fold desc="事件包装">
    selectAllEvent ({ checked }) {
      const records = this.$refs.tableRef.getCheckboxRecords()
      this.$emit('selection-change',records)
      this.$emit('selectionChange',records)
    },
    selectChangeEvent ({ checked }) {
      const records = this.$refs.tableRef.getCheckboxRecords()
      this.$emit('selection-change',records)
      this.$emit('selectionChange',records)
    },
    cellMouseleave({ row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, $event }){
      this.$nextTick(() => {
        this.$refs.tableRef.$refs.validTip?.close()
      })
      this.$emit('cell-mouseleave',{ row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, $event })
      this.$emit('cellMouseleave',{ row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, $event })
    }
    //</editor-fold>
  }
}
</script>

<style lang="scss">
.vue-treeselect__portal-target.vue-treeselect.vue-treeselect--searchable.vue-treeselect--open-below.vue-treeselect--append-to-body{
  min-width: 500px;
}
</style>
